const fs = require('fs');

class ConfigManager {
  constructor() {
    this.configTemplate = {
      id: "60",
      totalplates: 790,
      plc: "192.168.1.51",
      ResourceID: "100", //在BSM报文中的转盘编号,如果是垃圾转盘或者暂时屏蔽，填null
      MatchPoint: 10,// 匹配点，虚拟概念，应该位于RFID和传感器的后面
      MatchPointScreenStart: 5, //如果匹配点位于某个屏幕内，填写屏幕的起始位置，否则填写null
      MatchPointScreenOffsetPix: 30, //如果匹配点位于某个屏幕内，填写距离屏幕起点的偏移量，单位为像素
      MonitorHeight: 64, //屏幕高度，对于LED屏，如西安为64像素高，对于显示屏如深圳，为1080
      MonitorWidth: 1536, //单块屏幕宽度，以西安为例，LED屏不能充分利用整个屏幕，而是在1536处换行；对于显示器，填写实际宽度，如深圳为1920
      background: "usbcam", //usbcam/black/....
      direction: "left-right", // right-left
      layerHeight: 16, //行李标签显示的高度，单位为像素
      presetStep: 3, // 预设速度，每帧移动的像素数
      styleDefualt: {
        color: "green"
      },
      detector: [
        {
          position: 0,
          type: "main",
          beforeRFID: false, // 在RFID前方，且不在RFID覆盖范围内，其它情况都是false
          offset: 4800,
          scale: 200
        },
        {
          position: 32,
          type: "tracker",
          beforeRFID: true,
          offset: 4800,
          scale: 200
        }
      ],
      flightInfoUrl: "http://10.51.8.170:3000/get_value",
      rfid: [
        {
          ip: "192.168.1.63",
          port: 2112,
          position: 10,
          // RFID读取标签的覆盖范围，指的是标签刚刚读到的时候的范围，而不是持续读取的范围
          // 参考设计文档
          startPlate: 1005,
          endPlate: 10,
          BottomAntennaNo: 100
        }
      ],
      threshold: {
        intervalBetweenTwoRead: 1000, // 两次plc读取之间的最小时间间隔，单位为毫秒
        lablesLifeTimeSecs: 7200, // 行李标签彻底删除的时间，单位为秒
        timeasStillSecs: 10,
        scanningTimeMS: 1000, //认为标签能被读到的时间，单位为毫秒。RFID持续发送读到的标签，超过这个时间没有被读到，认为读不到了
        deltaHeight: 20, // 高度变化阈值
        minWindowHeight: 10, //最小行李的高度阈值
        minWindowLength: 4, //最小行李的鳞片数阈值
        newWindowHeight: 1.5
      },
      template: {
        // 行李标签的模板，默认使用第一个模板
        color: "green",
        fontSize: "70px",
        fontFamily: "Arial",
        width: "300px",
      },
      captureArea: { // USB相机截取区域
        x: 40,
        y: 20,
        width: 1070,
        height: 700
      },
      camara: {
        width: 1920, // 请求的摄像头分辨率
        height: 1080, // 请求的摄像头分辨率
        fps: 30,
        brightness: 100,
        contrast: 100,
        saturation: 100,
        hue: 0
      },
      camara_carousel: [
        {
          url: "rtsp://admin:HIK123456@192.168.1.64:554/h264/ch1/main/av_stream",
          position: 108
        }
      ],
      screen: [
        {
          start: 60,
          len_pix: 3072, //可以填config.monitorWidth的倍数
        },
        {
          start: 545,
          len_pix: 2200
        }
      ],
      workStation: [
        {
          startScale: 0,
          endScale: 10000
        },
        {
          startScale: 150,
          endScale: 200
        },
        {
          startScale: 260,
          endScale: 310
        }
      ]
    };
  }

  async loadConfig(url) {
    const localConfig = "test/config.json";
    try {
      if (fs.existsSync(localConfig)) {
        console.log("Loading local configuration...");
        const config = JSON.parse(fs.readFileSync(localConfig, "utf8"));
        return config;
      } else {
        console.log("Loading remote configuration...");
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const config = await response.json();
        return config;
      }
    } catch (error) {
      console.error("Failed to load configuration:", error.message);
      error.isLoadError = true; // 标记为加载错误
      throw error;
    }
  }

  validateConfig(config) {
    const errors = [];
    // 遍历模板中的所有字段进行验证
    for (const [field, value] of Object.entries(this.configTemplate)) {
      // 检查字段是否存在
      if (!(field in config)) {
        errors.push(`Missing required field: ${field}`);
        continue;
      }

      // 检查数组类型字段
      if (Array.isArray(value)) {
        if (!Array.isArray(config[field]) || config[field].length < 1) {
          errors.push(`Field ${field} must be an array with at least one element`);
          continue;
        }

        // 递归验证数组中的每个元素
        for (let i = 0; i < config[field].length; i++) {
          const item = config[field][i];
          for (const [templateKey, templateValue] of Object.entries(value[0])) {
            if (!(templateKey in item)) {
              errors.push(`Missing required field '${templateKey}' in ${field}[${i}]`);
            }
          }
        }
      }
    }

    if (errors.length > 0) {
      throw new Error('Configuration validation failed:\n' + errors.join('\n'));
    }
    return true;
  }
}

// 如果直接运行此文件，执行配置验证
if (require.main === module) {
  const configPath = process.argv[2] || 'test/config.json';
  try {
    const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
    const configManager = new ConfigManager();
    configManager.validateConfig(config);
    console.log('\x1b[32m%s\x1b[0m', '✓ 配置验证通过！');
  } catch (error) {
    console.error('\x1b[31m%s\x1b[0m', '✗ 配置验证失败：');
    if (error instanceof SyntaxError) {
      console.error('  JSON解析错误：', error.message);
    } else {
      console.error('  ' + error.message.replace(/\n/g, '\n  '));
    }
    process.exit(1);
  }
}

module.exports = new ConfigManager();

